/**
 * @FileName: ExportService.java
 * @Author
 * @Description:
 * @Date 2016年4月13日 下午2:44:12
 * @CopyRight ZTE Corporation
 */
package cn.hpclub.server.service.ds;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.List;

import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;

import cn.hpclub.server.service.ds.DateUtils.SyncParams;

public abstract class ExportTextDataService{
    protected static final String FILE_EXTENSION = ".txt";
    private static final int      PAGE_SIZE      = 5000;
    protected SyncParams          params;
    protected FtpParam            ftpParam;

    /**
     * @Title: getSql
     * @Description:获取查询数据SQL语句
     * @param params:导出参数
     * @return String SQL语句
     */
    abstract String getSql(SyncParams params);

    /**
     * @Title: getFileName
     * @Description:获取导出TEXT文件名
     * @param params:导出参数
     * @return String SQL语句
     */
    abstract String getFileName(SyncParams params);

    /**
     * @Title: convertRecordToString
     * @Description:把查询的Record转换为String类型
     * @param item
     * @return char[]
     */
    abstract String convertRecordToString(Record item);

    /**
     * @Title: getFilePath
     * @Description:获取文件保存路径
     * @param fileName:文件名
     * @return String 文件路径
     */
    abstract String getFilePath(String fileName);

    /**
     * @Title: exportAndUpload
     * @Description:导出并上传文件 void
     */
    public void exportAndUpload(){
        DsLog.log(params.logTag + " 导出开始：" + params.toString());
        CmccFtpUtil ftpUtils = getCmccFtpUtil(ftpParam);
        try{
            String filePath = exportDataByParams(params);
            saveExportResult(params, filePath);
            upload(params, params.logTag, ftpUtils, filePath);
        }
        catch(IOException e){
            e.printStackTrace();
            DsLog.log(params.logTag + " 流程失败：" + params.toString() + "error:" + e.getMessage());
        }
        finally{
            ftpUtils.closeConnection();
        }
    }

    private void upload(SyncParams params, String type, CmccFtpUtil ftpUtils, String filePath)
            throws FileNotFoundException, IOException{
        FileInputStream fis;
        fis = new FileInputStream(filePath);
        DsLog.log(type + " 数据上传FTP服务器：" + params.toString() + ":" + ftpUtils.getServerIp() + ":" + filePath + ". size="
                + fis.available());
        ftpUtils.uploadFile(getFileName(params), fis);
        fis.close();
        DsLog.log(type + " 数据上传深圳服务器完成：" + params.toString());
    }

    private CmccFtpUtil getCmccFtpUtil(FtpParam ftpParam){
        return new CmccFtpUtil(ftpParam.host, ftpParam.port, ftpParam.account, ftpParam.password, ftpParam.encoding,
                ftpParam.remotePath);
    }

    /**
     * @Title: saveExportResult
     * @Description:TODO
     * @param params
     * @param filePath
     *            void
     */

    abstract void saveExportResult(SyncParams params, String filePath);

    private String exportDataByParams(SyncParams params) throws IOException{
        String sql = getSql(params);
        int i = 0;
        OutputStreamWriter osr = null;
        try{
            String filePath = getFilePath(getFileName(params));
            osr = new OutputStreamWriter(new FileOutputStream(new File(filePath)), "gbk");
            while(true){
                List<Record> list = Db.find(String.format("%s LIMIT %d, %d", sql, i * PAGE_SIZE, PAGE_SIZE));
                if(list.isEmpty()){
                    break;
                }
                outputToFile(list, osr);
                i++;
            }
            return filePath;
        }
        finally{
            closeWriter(osr);
        }
    }

    private void closeWriter(OutputStreamWriter osr){
        if(osr != null){
            try{
                osr.close();
            }
            catch(IOException e){
                e.printStackTrace();
            }
        }
    }

    private void outputToFile(List<Record> list, OutputStreamWriter osr) throws IOException{
        for(int i = 0; i < list.size(); i++){
            Record item = list.get(i);
            osr.write(convertRecordToString(item));
            osr.write("\r\n");
        }
    }

    public static class FtpParam{
        public String host;
        public int    port;
        public String account;
        public String password;
        public String encoding;
        public String remotePath;

        public FtpParam(String host, int port, String account, String password, String encoding, String remotePath){
            this.host = host;
            this.port = port;
            this.account = account;
            this.password = password;
            this.encoding = encoding;
            this.remotePath = remotePath;
        }
    }
}
